
#include <netinet/in.h>
#include <cstdlib>
#include <cstring>
#include <cerrno>
#include <iostream>
#include <cstdio>
#include <csignal>

using namespace std;

static const int SOCK_ERR = -1;
static const int BACKLOG = 5;
static const unsigned BUF_SIZE = 2000;

void error() {
    exit(-1);
}

void sigh( int i) {
	cout << "got : " << i << endl;
}

#define IGNORE_EINTR(s) do { while( -1 == ( s ) ) {} } while(0)

int main( int argc, char *argv[] ) {

	// signal( 1, SIG_IGN );
	signal( 2, sigh );
    
    int sock( socket(AF_INET, SOCK_STREAM, 0 ) );

    if ( SOCK_ERR == sock ) {
        error();
    }

    static const int enable_reuse(1);
    if ( SOCK_ERR == setsockopt( sock, SOL_SOCKET,
                                 SO_REUSEADDR, &enable_reuse, 
                                 sizeof(enable_reuse))) {
        close( sock );
        error();
    }

    struct sockaddr_in address;
    memset( &address, 0, sizeof(address) );
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = htonl(INADDR_ANY);
    address.sin_port = htons(1090);

    if ( SOCK_ERR == bind( sock, 
                           (struct sockaddr *)&address, 
                           sizeof(address) ) ) {
        close( sock );
        error();
    }

    if ( SOCK_ERR == listen( sock, BACKLOG ) ) {
        close( sock );
        error();
    }

    while ( 1 ) {
        struct sockaddr_in peer_addr;
        memset( &peer_addr, 0, sizeof(peer_addr) );
        socklen_t peer_addr_len(0);
		int peer_sock = -1;
        IGNORE_EINTR( peer_sock = accept( sock, 
										  (struct sockaddr*)&peer_addr, 
										  &peer_addr_len ) );

        if ( SOCK_ERR == peer_sock ) {
            switch( errno ) {
			  case EINTR:
				cout << "hi " << endl;
				continue;
              default:
                close( peer_sock );
                close( sock );
                error();
            }
        }

        char buf[BUF_SIZE];
        const int bread = recv( peer_sock, buf, BUF_SIZE, 0 );
        if ( SOCK_ERR == bread ) {
            close( peer_sock );
            close( sock );
            error();
        }

        buf[bread] = '\0';

        // HTTP/1.0 200 OK 
        // Date: Fri, 08 Aug 2003 08:12:31 GMT 
        // Server: Apache/1.3.27 (Unix) 
        // MIME-version: 1.0 
        // Last-Modified: Fri, 01 Aug 2003 12:45:26 GMT 
        // Content-Type: text/html 
        // Content-Length: 2345 
        // ** a blank line * 
        // <HTML> ...

        struct tm;
        time_t now;
        time( &now );
        char *ascnow = ctime( &now );

        const size_t len = sprintf( buf, "HTTP/1.0 200 OK\n\n"
                                    "<HTML><HEAD></HEAD><P ALIGN=CENTER>SUCCESS!</P>"
                                    "<P ALIGN=CENTER>%s</P></HTML>", ascnow );

        if ( len != (unsigned)send( peer_sock, buf, len, 0 ) ) {
            close( peer_sock );
            close( sock );
            error();
        }
                 
        close( peer_sock );
    }
    
    return 0;
}
